package com.xscha.soyue.common.core.utils;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.xscha.soyue.common.core.exception.SoyRuntimeException;
import com.xscha.soyue.common.core.json.BeanJsonService;
import com.xscha.soyue.common.core.json.JacksonBeanJsonService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Json工具类
 *
 * @author Vondser
 * @version V2024.1.0
 */
@Slf4j
public class JsonUtils {

	private JsonUtils() {
	}

	private static volatile BeanJsonService BEAN_JSON_SERVICE;

	static {
		log.info("初始化BeanJsonUtils...");
		BEAN_JSON_SERVICE = new JacksonBeanJsonService();
	}

	public static void setBeanJsonService(BeanJsonService beanJsonService) {
		synchronized (JsonUtils.class) {
			if (log.isDebugEnabled()) {
				log.info("设置BeanJsonUtils中的BeanJsonService...");
			}
			BEAN_JSON_SERVICE = beanJsonService;
		}
	}

	public static String toJson(Object object) throws SoyRuntimeException {
		return BEAN_JSON_SERVICE.toJson(object);
	}

	@SneakyThrows
	public static String toJsonString(Object object) {
		return BEAN_JSON_SERVICE.toJsonString(object);
	}

	@SneakyThrows
	public static <T> T parseObject(byte[] bytes, Class<T> clazz) {
		if (ArrayUtil.isEmpty(bytes)) {
			return null;
		}
		return BEAN_JSON_SERVICE.parseObject(bytes, clazz);
	}

	@SneakyThrows
	public static <T> T parseObject(String text, Class<T> clazz) {
		if (StrUtil.isEmpty(text)) {
			return null;
		}
		return BEAN_JSON_SERVICE.parseObject(text, clazz);
	}

	@SneakyThrows
	public static <T> T parseObject(String text, TypeReference<T> typeReference) {
		return BEAN_JSON_SERVICE.parseObject(text, typeReference);
	}

	@SneakyThrows
	public static <T> List<T> parseArray(String text, Class<T> clazz) {
		if (StrUtil.isEmpty(text)) {
			return new ArrayList<>();
		}

		return BEAN_JSON_SERVICE.parseArray(text, clazz);
	}

	@SneakyThrows
	public static JsonNode parseTree(String text) {
		return BEAN_JSON_SERVICE.parseTree(text);
	}

	/**
	 * 转换成为list
	 */
	public static <T> List<T> toList(String source, Class<T> clz) throws SoyRuntimeException {
		return BEAN_JSON_SERVICE.toList(source, clz);
	}

	/**
	 * 转换成为set
	 */
	public static <T> Set<T> toSet(String source, Class<T> clz) throws SoyRuntimeException {
		return BEAN_JSON_SERVICE.toSet(source, clz);
	}

	/**
	 * 转换成为key 类型为 string 的map
	 */
	public static <V> Map<String, V> toStringKeyMap(String source, Class<V> vlz) throws SoyRuntimeException {
		return BEAN_JSON_SERVICE.toMap(source, String.class, vlz);
	}

	public static Map<String, Object> toMap(Object obj) throws SoyRuntimeException {
		return BEAN_JSON_SERVICE.toMap(obj);
	}

	/**
	 * 转换成为map
	 */
	public static <K, V> Map<K, V> toMap(String source, Class<K> klz, Class<V> vlz) throws SoyRuntimeException {
		return BEAN_JSON_SERVICE.toMap(source, klz, vlz);
	}

	/**
	 * 转换成为对象
	 */
	public static <T> T toObject(String source, Class<T> clz) throws SoyRuntimeException {
		return BEAN_JSON_SERVICE.toObject(source, clz);
	}

	/**
	 * 转换成为对象
	 */
	public static <T> T toObject(String source, Type target) throws SoyRuntimeException {
		return BEAN_JSON_SERVICE.toObject(source, target);
	}

	public static <T> T toObject(String source, Class<?> parametrized, Class<?>... parameterClasses) {
		return BEAN_JSON_SERVICE.toObject(source, parametrized, parameterClasses);
	}

	/**
	 * 转换成为对象
	 */
	public static <T> T toObject(String source, TypeReference<T> type) throws SoyRuntimeException {
		return BEAN_JSON_SERVICE.toObject(source, type);
	}

	public static Object getMapper() {
		return BEAN_JSON_SERVICE.getMapper();
	}

	public static void writeValue(HttpServletResponse response, Object o) {
		BEAN_JSON_SERVICE.writeValue(response, o);
	}

	public static <T> T readValue(String json, Class<T> tClass) {
		return BEAN_JSON_SERVICE.readValue(json, tClass);
	}

}
